package com.google.code.stalkernet.peer;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import com.google.code.stalkernet.message.Message;
import com.google.code.stalkernet.peer.event.PeerEvent;
import com.google.code.stalkernet.peer.event.PeerListener;

/**
 * Abstract base class for implementations of Peer interface.
 *
 * @author Mikhail Vladimirov
 */
public abstract class AbstractPeer implements Peer
{
    private final List <PeerListener> peerListeners =
        new CopyOnWriteArrayList <> ();

    /**
     * {@inheritDoc}
     */
    @Override
    public void addPeerListener (PeerListener peerListener)
    {
        if (peerListener == null)
            throw new IllegalArgumentException ("Peer listener is null");

        peerListeners.add (peerListener);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removePeerListener (PeerListener peerListener)
    {
        if (peerListener == null)
            throw new IllegalArgumentException ("Peer listener is null");

        peerListeners.remove (peerListener);
    }

    /**
     * Get all registered peer listeners.
     *
     * @return an array of {@link PeerListener} objects
     */
    public PeerListener [] getAllPeerListeners ()
    {
        return peerListeners.toArray (new PeerListener [peerListeners.size ()]);
    }

    /**
     * Notify all registered listeners that message was received from peer.
     *
     * @param message received {@link Message}
     */
    protected void fireMessageReceived (Message message)
    {
        if (message == null)
            throw new IllegalArgumentException ("Message is null");

        PeerEvent peerEvent = null;

        for (PeerListener peerListener: peerListeners)
        {
            if (peerEvent == null) peerEvent = new PeerEvent (this, message);

            peerListener.messageReceived (peerEvent);
        }
    }

    /**
     * Notify all registered listeners that peer was disconnected.
     */
    protected void fireDisconnected ()
    {
        PeerEvent peerEvent = null;

        for (PeerListener peerListener: peerListeners)
        {
            if (peerEvent == null) peerEvent = new PeerEvent (this);

            peerListener.disconnected (peerEvent);
        }
    }
}
